home *** CD-ROM | disk | FTP | other *** search
- /*++
- /* NAME
- /* desk 3
- /* CATEGORY
- /* mail box display
- /* PROJECT
- /* pc-mail
- /* PACKAGE
- /* mail
- /* SYNOPSIS
- /* #include "mail.h"
- /*
- /* void init()
- /*
- /* int junk_desk()
- /*
- /* char message[];
- /* char comment[];
- /* DESCRIPTION
- /* Most functions in this module are invoked by the keyboard interpreter
- /* and are responsible for the mail box view of message summary lines.
- /*
- /* init() is the main entry point. It presents the user with a display
- /* of message categories (create, unread, already seen, unsent, sent,
- /* in preparation), and the number of messages in each category. After
- /* the user has chosen a category, an editor is invoked, or a sorted
- /* display of all messages in the respective category is displayed.
- /*
- /* junk_desk() should be invoked when the number of files in the mail box
- /* may have changed. Always returns a zero value. This function
- /* should be called when a message is added to, or deleted from, the
- /* spool directory.
- /*
- /* The strings "message" and "comment" hold path names of the currently
- /* selected message file, and its associated meta file (with message
- /* destination, origin or comments). These names are used by functions
- /* that read, delete or otherwise manipulate message files.
- /* FILES
- /* mail header files in the spool directory
- /* SEE ALSO
- /* pager(3), pager(5), kbdinp(3)
- /* DIAGNOSTICS
- /* If a selected mail message could not be found an error message
- /* is displayed instead.
- /* BUGS
- /* Since a message can be accessed only if its metafile exists,
- /* a message is "lost" when for some reason the metafile is
- /* not available.
- /* AUTHOR(S)
- /* W.Z. Venema
- /* Eindhoven University of Technology
- /* Department of Mathematics and Computer Science
- /* Den Dolech 2, P.O. Box 513, 5600 MB Eindhoven, The Netherlands
- /* CREATION DATE
- /* Tue May 12 15:35:20 GMT+1:00 1987
- /* LAST MODIFICATION
- /* 90/01/22 13:01:29
- /* VERSION/RELEASE
- /* 2.1
- /*--*/
-
- #include <stdio.h>
- #include <ctype.h>
- #include <errno.h>
- #include <sys/types.h>
- #include <sys/stat.h>
- #include <time.h>
-
- #include "defs.h"
- #include "mail.h"
- #include "path.h"
- #include "ndir.h"
- #include "pager.h"
- #include "screen.h"
- #include "status.h"
- #include "window.h"
- #include "ascf.h"
- #include "snapshot.h"
-
- hidden void make_desk(); /* forward declarations */
- hidden int pick_desk();
- hidden int show_desk();
- hidden void desk();
- hidden void make_init();
- hidden int pick_init();
- hidden int show_init();
- hidden char *singular();
-
- hidden File *deskfile = 0; /* mail box pager file */
- hidden File *initfile = 0; /* initial screen */
- public char message[BUFSIZ]; /* path to message file */
- public char comment[BUFSIZ]; /* path to meta file */
-
- /* Definitions of the various message categories */
-
- typedef struct {
- char *type; /* work, incoming, outgoing, ... */
- char mesg; /* message-file prefix */
- char meta; /* meta-file prefix */
- int (*access) (); /* message access function */
- int flags; /* see below */
- char *whatsit; /* explanation */
- } CATEGORY;
-
- #define MULT 1 /* multi-message category */
- #define DMON 2 /* subject to daemon activity */
-
- hidden CATEGORY categories[] = {
- "Create", WORK_MESG, WORK_META, create,0, "Create a new message",
- "Work", WORK_MESG, WORK_META, work, MULT, "Message%S in preparation",
- "New", NEW_MESG, NEW_META, mbox, MULT|DMON,"Unread message%S",
- "In", OLD_MESG, OLD_META, mbox, MULT, "Message%S already read",
- "Out", OUT_MESG, OUT_META, mbox, MULT|DMON,"Message%S not-yet sent",
- "Sent", SENT_MESG, SENT_META, mbox, MULT|DMON,"Message%S already sent",
- 0, /* terminator */
- };
-
- hidden CATEGORY *category; /* selected message category */
-
- /* table with all meta-file name prefixes */
-
- hidden char metalist[] = {
- WORK_META, NEW_META, OLD_META, OUT_META, SENT_META, 0,
- };
-
- hidden char initsingle[] = "%-6s %5s %s";
- hidden char initmulti[] = "%-6s %5u %s";
- hidden char scanmulti[] = "%s %u";
-
- hidden char dispfmt[] = "%5u %.16s %.53s";
- hidden char dispfmts[] = "%5u %.16s %.40s \"%s\"";
- hidden char scanfmt[] = "%u";
-
- /* init - main entry point for message manipulations */
-
- public void init()
- {
- static Screen screen[] = {
- 'C', "Close", 0, "Terminate the program",
- 'F', "File", file, "Mail a copy of an ordinary file",
- #ifndef DAEMON
- 'N', "Network", call, "Exchange mail with the network",
- #endif
- 'S', "Setup", setup, "Set communications parameters",
- 'A', "Alias", alias, "Display the alias data base",
- 'P', "Print", print, "Print contents of this display",
- UP, "Up", up_pager, csrup,
- DOWN, "Down", dn_pager, csrdn,
- ENTER, "Enter", pick_init, "Select message category",
- 0, 0, show_init,
- "Select a message category with cursor keys and press ENTER\n\
- or select one of the commands in the top line."
- };
-
- kbdinp(screen); /* and there they go... */
- }
-
- /* show_init - create or refresh the initial screen */
-
- hidden int show_init()
- {
- if (initfile == 0) { /* no initial screen file */
- patience(); /* one moment please */
- make_init(initfile = open_pager()); /* build initial screen */
- } else { /* pager file exists */
- set_pager(initfile); /* select pager file */
- }
- ds_pager(); /* display it */
- return (0); /* screen is ok */
- }
-
- /* junk_init - force re-scan of mail directory and re-build of initial screen */
-
- hidden void junk_init()
- {
- if (initfile) {
- close_pager(initfile);
- initfile = 0;
- }
- snap_junk(); /* re-scan mail directory */
- }
-
- /* make_init - build initial screen */
-
- hidden void make_init(pp)
- File *pp;
- {
- register SNAP_SHOT *s;
- register unsigned count;
- register CATEGORY *c;
-
- /*
- * In case of multi-message categories, show the number of messages in
- * that category.
- */
-
- for (c = categories; c->type; c++) {
- if (c->flags & MULT) { /* multi-message category */
- for (count = 0, s = snap_shot(metalist); s->prefix; s++)
- if (c->meta == s->prefix)
- count++;
- app_pager(pp, strcons(initmulti, c->type, count,
- singular(count, c->whatsit)));
- } else { /* single-message category */
- app_pager(pp, strcons(initsingle, c->type, "", c->whatsit));
- }
- }
- pp->opts |= PG_NOEND; /* suppress 'end-of-display' */
- }
-
- /* exec_msg - execute access function for a particular message */
-
- hidden int exec_msg(msgno)
- unsigned msgno;
- {
- (void) strcpy(message, mesg_file(category->mesg, msgno));
- (void) strcpy(comment, meta_file(category->meta, msgno));
- return (CALL(category->access) (category->meta, msgno));
- }
-
- /* pick_init - user selected a message category */
-
- hidden int pick_init()
- {
- char type[BUFSIZ];
- register CATEGORY *c;
- unsigned count;
-
- /*
- * Read the message type (in, out, work etc) from the summary line in the
- * initial display.
- *
- * On systems that do not use daemons for message delivery, disallow
- * selection an empty message category.
- */
-
- count = type[0] = 0; /* initialize */
- (void) sscanf(gets_pager(), scanmulti, type, &count);
-
- for (c = categories; c->type; c++) { /* try to recognize the */
- if (strcmp(c->type, type) == 0) { /* message type */
- category = c; /* GLOBAL! */
- if ((c->flags & MULT) == 0) { /* create-message category */
- return (exec_msg(newseqno()));
- #ifndef DAEMON
- } else if (count == 0) { /* multi-message, empty */
- break;
- #endif
- } else { /* multi-message */
- desk();
- return (S_REDRAW);
- }
- }
- }
- beep(); /* error */
- return (0); /* nothing happened */
- }
-
- /* desk - manipulate one category of messages */
-
- hidden void desk()
- {
- static Screen screen[] = {
- 'C', "Close", 0, initscreen,
- 'F', "File", file, "Mail a copy of an ordinary file",
- #ifndef DAEMON
- 'N', "Network", call, "Exchange mail with the network",
- #endif
- 'S', "Setup", setup, "Set communications parameters",
- 'A', "Alias", alias, "Display the alias data base",
- 'P', "Print", print, "Print contents of this display",
- PGUP, PgUp, pu_pager,pageup,
- PGDN, PgDn, pd_pager,pagedn,
- UP, "Up", up_pager,csrup,
- DOWN, "Down", dn_pager,csrdn,
- ENTER, "Enter", pick_desk,"Select message",
- 0, 0, show_desk,
- "Select a message with the cursor keys and press ENTER\n\
- or select one of the commands in the top line."
- };
-
- /*
- * On systems where daemon processes take care of message delivery, we
- * re-scan the mail directory if the user selects a message category that
- * can be affected by daemon activity, and force a re-scan of the mail
- * directory upon return to the initial screen (unless that just happened
- * as a result of some user action).
- */
-
- #ifdef DAEMON
- if (category->flags & DMON) /* if affected by daemons */
- junk_init(); /* re-scan mail directory */
- #endif
- kbdinp(screen);
- #ifdef DAEMON
- junk_init(); /* re-scan mail directory */
- #endif
- close_pager(deskfile);
- deskfile = 0;
- }
-
- /* show_desk - create or refresh a display of a mail box selection */
-
- hidden int show_desk()
- {
- if (deskfile == 0) { /* no mail box pager file */
- patience(); /* one moment please... */
- make_desk(deskfile = open_pager()); /* build mail box display */
- } else { /* pager file exists */
- set_pager(deskfile); /* select pager file */
- }
- ds_pager(); /* display it */
- return (0); /* screen is ok */
- }
-
- /* make_desk - build display of summary lines of selected message type */
-
- hidden void make_desk(pp)
- File *pp;
- {
- FILE *fp; /* used to read meta info */
- char ident[MAXLINE]; /* usually person\'s name or address */
- char subj[MAXLINE]; /* subject info */
- char *line;
- register SNAP_SHOT *s; /* snapshot table */
- struct stat st;
-
- /*
- * The message sequence number and type are already known; we just have
- * to retrieve from the meta file: a person\'s name or address (first
- * line) and an optional subject (second line).
- *
- * If Subject: information is present we truncate the person\'s name or
- * address to (screen width - 40) columns. Any text that extends beyond
- * the width of the screen is truncated as well.
- */
-
- for (s = snap_shot(metalist); s->prefix; s++) {
- if ((s->prefix == category->meta)
- && (fp = ascopen(meta_file(s->prefix, s->msgno), "r"))) {
- if ((ascgets(ident, sizeof(ident), fp) != 0)
- && (fstat(fileno(fp), &st) == 0)) {
- if (ascgets(subj, sizeof(subj), fp) && subj[0]) {
- /* subject found; truncate person\'s name or address */
- if (strlen(ident) > CO - 40)
- (void) strcpy(ident + CO - 42, "..");
- line = strcons(dispfmts, s->msgno,
- tstamp(&(st.st_mtime)), ident, subj);
- } else {
- /* no subject info */
- line = strcons(dispfmt, s->msgno,
- tstamp(&(st.st_mtime)), ident);
- }
- /* truncate final result anyway */ if (strlen(line) >= CO - 1)
- (void) strcpy(line + CO - 3, "..");
- app_pager(pp, line);
- }
- ascclose(fp);
- }
- }
-
- /* sort summary lines in reverse order, i.e. newest comes first */
-
- sort_pager(pp, BACK_SORT);
- }
-
- /* pick_desk - user selected a message */
-
- hidden int pick_desk()
- {
- unsigned msgno;
-
- /*
- * Read message sequence number from summary line in the mail box
- * display. Build actual message file and meta file names. Then call the
- * appropriate function to access that message.
- */
-
- msgno = 0; /* initialize */
- (void) sscanf(gets_pager(), scanfmt, &msgno);
-
- if (msgno) {
- return (exec_msg(msgno));
- } else {
- beep(); /* unrecognized message id */
- return (0); /* nothing happened */
- }
- }
-
- /* junk_desk - force rebuilding of mail box display */
-
- public int junk_desk()
- {
- if (deskfile) {
- close_pager(deskfile); /* delete pager file */
- deskfile = 0; /* say it's gone */
- }
- junk_init(); /* and re-scan mail directory */
- return (0); /* in case one wants it */
- }
-
- /* singular - replace %S depending on whether a count is 1 */
-
- hidden char *singular(c, s)
- int c;
- register char *s;
- {
- static char buf[BUFSIZ];
- register char *bp = buf;
-
- while (*s) {
- if (*s == '%') {
- if (s[1] == 'S') { /* expand %S */
- if (c != 1)
- *bp++ = 's';
- s += 2;
- } else if (s[1] == '\0') { /* don\'t fall off end */
- *bp++ = *s++;
- } else { /* leave %<any> alone */
- *bp++ = *s++, *bp++ = *s++;
- }
- } else {
- *bp++ = *s++;
- }
- }
- *bp = '\0';
- return (buf);
- }
-